蜂鳴器(Buzzer)是一種將電信號轉換為聲音信號的電子元件,常見於各類電子裝置中,作為警報、提示音或音樂播放的工具。蜂鳴器的工作原理與其類型密切相關,主要可分為有源蜂鳴器和無源蜂鳴器兩大類。
有源蜂鳴器內部包含震盪器,只需要通電即可發聲,發聲頻率通常是固定的。使用這種蜂鳴器時,只需給它供電(通常是5V或12V),蜂鳴器便會發出預設的聲音,無需外部的信號控制。
無源蜂鳴器不包含內部震盪器,因此需要外部提供脈衝信號來驅動發聲。聲音的頻率可以由脈衝信號的頻率來控制,因此無源蜂鳴器可以用來產生不同頻率的聲音,如音樂音符。常見的控制方法是使用 PWM(脈衝寬度調變)來驅動,改變脈衝的頻率即可改變發聲頻率。
參考英文維基百科條目「Scientific_pitch_notation」,我們可以先來定義 88鍵鋼琴常用的琴鍵對應頻率。
也就是我們會定義常用的三個八度音,使用音樂標記,將頻率與音樂標記做成一張對照表。,讓我們平常輸入樂譜時更便利。
tones = {
"A2": 110,"AS2": 117,"B2": 123,"C3": 131,"CS3": 139,
"D3": 147,"DS3": 156,"E3": 165,"F3": 175,"FS3": 185,"G3": 196,"GS3": 208,"A3": 220,"AS3": 233,"B3": 247,
"C4": 262,"CS4": 277,"D4": 294,"DS4": 311,"E4": 330,"F4": 349,"FS4": 370,"G4": 392,"GS4": 415,"A4": 440,"AS4": 466,"B4": 494,
"C5": 523,"CS5": 554,"D5": 587,"DS5": 622,"E5": 659,"F5": 698,
"FS5": 740,"G5": 784,"GS5": 831,"A5": 880,"AS5": 932,"B5": 988,
"C6": 1047,"CS6": 1109,"D6": 1175,"DS6": 1245,"E6": 1319,"F6": 1397,"FS6": 1480,"G6": 1568,"GS6": 1661,
"A6": 1760,"AS6": 1865,"B6": 1976,
"C7": 2093,"CS7": 2217,"D7": 2349,"DS7": 2489,"E7": 2637,"F7": 2794,"FS7": 2960,"G7": 3136,"GS7": 3322,"A7": 3520,"AS7": 3729,"B7": 3951,
"C8": 4186,"CS8": 4435,"D8": 4699,"DS8": 4978
}
因為玩學機內建的蜂鳴器是無源式的,所以發音時,我們要搭配系統的PWM功能一起使用。
from machine import Pin, PWM
from time import sleep
# 蜂鳴器設定
snd_PinA = Pin(17, 2).value(1)
snd_PinB = Pin(25, 2)
snd = PWM(snd_PinB)
def play(freq, t):
snd.duty(80)
snd.freq(freq)
sleep(t)
snd.duty(0)
# 01. 發出單音 Do C4
play(262, 1)
snd.deinit() # 關閉 Buzz
from machine import Pin, PWM
from time import sleep
# 蜂鳴器設定
snd_PinA = Pin(17, 2).value(1)
snd_PinB = Pin(25, 2)
snd = PWM(snd_PinB)
# 發聲程式
def play(freq, t):
snd.duty(50)
snd.freq(freq)
sleep(t)
snd.duty(0)
# 演奏音階
frq = 30
freq = 30
for i in range(64):
print(freq)
play(freq, 0.2)
freq = int(freq * 1.15)
# 關閉 PWM
snd.deinit()
我們在網路上找到一個 Raspberry Pi Pico 的範例,改成可以在玩學機上使用的程式。
原始介紹網頁在此:
https://www.coderdojotc.org/micropython/sound/05-play-mario/
from machine import Pin, PWM
from time import sleep
# 蜂鳴器設定
snd_PinA = Pin(17, 2).value(1)
snd_PinB = Pin(25, 2)
snd = PWM(snd_PinB)
tones = {
"A2": 110,"AS2": 117,"B2": 123,"C3": 131,"CS3": 139,
"D3": 147,"DS3": 156,"E3": 165,"F3": 175,"FS3": 185,"G3": 196,"GS3": 208,"A3": 220,"AS3": 233,"B3": 247,
"C4": 262,"CS4": 277,"D4": 294,"DS4": 311,"E4": 330,"F4": 349,"FS4": 370,"G4": 392,"GS4": 415,"A4": 440,"AS4": 466,"B4": 494,
"C5": 523,"CS5": 554,"D5": 587,"DS5": 622,"E5": 659,"F5": 698,
"FS5": 740,"G5": 784,"GS5": 831,"A5": 880,"AS5": 932,"B5": 988,
"C6": 1047,"CS6": 1109,"D6": 1175,"DS6": 1245,"E6": 1319,"F6": 1397,"FS6": 1480,"G6": 1568,"GS6": 1661,
"A6": 1760,"AS6": 1865,"B6": 1976,
"C7": 2093,"CS7": 2217,"D7": 2349,"DS7": 2489,"E7": 2637,"F7": 2794,"FS7": 2960,"G7": 3136,"GS7": 3322,"A7": 3520,"AS7": 3729,"B7": 3951,
"C8": 4186,"CS8": 4435,"D8": 4699,"DS8": 4978}
def playtone(frequency):
snd.duty(50)
snd.freq(frequency)
def bequiet():
snd.duty(0)
def playsong(mysong):
for i in range(len(mysong)):
if (mysong[i] == "P" or mysong[i] == 0 ):
bequiet()
else:
playtone(tones[mysong[i]])
sleep(0.3)
bequiet()
mario = ["E5", "E5", 0, "E5", 0, "C5", "E5", 0, "G5", 0, 0, 0, "G4", 0, 0, 0, "C5", 0, 0, "G4",
0, 0, "E4", 0, 0, "A4", 0, "B4", 0, "AS4", "A4", 0, "G4", "E5", 0, "G5", "A5", 0, "F5", "G5",
0, "E5", 0,"C5", "D5", "B4", 0, 0, "C5", 0, 0, "G4", 0, 0, "E4", 0, 0, "A4", 0, "B4", 0,
"AS4", "A4", 0, "G4", "E5", 0, "G5", "A5", 0, "F5", "G5", 0, "E5", 0,"C5", "D5", "B4", 0, 0]
playsong(mario)
snd.deinit()